import { reactive, shallowRef, onUnmounted } from 'vue';
import { cloneDeep } from 'lodash';
import { FieldRule } from '@arco-design/web-vue';

import { hookResult } from './bindResult';

type RulesRecord<T> = {
  [key in keyof T]?: FieldRule | FieldRule[];
};

export interface SimpleFormProps<T> {
  state: T;
  rules?: RulesRecord<T>;
  labelCol?: {
    span?: number;
    offset?: number;
  };
  wrapperCol?: {
    span?: number;
    offset?: number;
  };
  onFinish?: (params: any) => void;
}

export function useForm<T extends Record<string, any>>(
  prop: SimpleFormProps<T>
) {
  const { state, rules, labelCol, wrapperCol } = prop;

  const initSnapshot = cloneDeep(state);

  const formLabelCol = labelCol || { span: 6 };
  const formWrapperCol = wrapperCol || { span: 18 };

  const formState = reactive<T>(state);

  const formRef = shallowRef<any>(null);

  function onFinish(params: any) {
    if (prop.onFinish) {
      prop.onFinish(params);
    }
  }

  function setFieldsValue(params: T) {
    Object.keys(params).forEach((key) => {
      // @ts-ignore
      formState[key] = params[key];
    });
    clearValidate();
  }

  function backToInit() {
    Object.keys(state).forEach((key) => {
      // @ts-ignore
      formState[key] = initSnapshot[key];
    });
    clearValidate();
  }

  function returnVerifyRef(method: (instance: any) => Promise<any>) {
    if (formRef.value) {
      return method(formRef.value);
    }
    return Promise.reject(new Error('表单formRef为null'));
  }

  function resetFields() {
    return returnVerifyRef((form) => {
      return form.resetFields();
    });
  }

  function clearValidate(...params: any[]) {
    return returnVerifyRef((form) => {
      return form.clearValidate(...params);
    });
  }

  function validate(...params: any[]) {
    return returnVerifyRef((form) => {
      // validate 结果优化
      return form.validate(...params).then((result: any) => {
        if (result) {
          return Promise.reject(result);
        }
        return true;
      });
    });
  }

  function rawValidate(...params: any[]) {
    return returnVerifyRef((form) => {
      // validate 结果优化
      return form.validate(...params);
    });
  }

  function scrollToField(...params: any[]) {
    return returnVerifyRef((form) => {
      return form.scrollToField(...params);
    });
  }

  function setRef(el: any) {
    formRef.value = el;
  }

  onUnmounted(() => {
    formRef.value = null;
  });

  return hookResult(
    {
      validate,
      state: formState,
      setFieldsValue,
      resetFields,
      clearValidate,
      scrollToField,
      backToInit,
      rawValidate,
    },
    {
      ref: setRef,
      model: formState,
      rules: rules as Record<string, FieldRule<any> | FieldRule<any>[]>,
      wrapperCol: formWrapperCol,
      labelCol: formLabelCol,
      onFinish,
    }
  );
}

export type TSimpleFormResult<T extends Record<string, any>> = ReturnType<
  typeof useForm<T>
>;
